package com.king.pages.novel.form;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

import org.kordamp.ikonli.feather.Feather;
import org.kordamp.ikonli.javafx.FontIcon;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

import com.king.App;
import com.king.event.FormDialogEvent;
import com.king.pages.novel.entity.Novel;
import com.king.pages.novel.entity.NovelVolume;
import com.king.pages.novel.service.NovelService;
import com.king.util.Async;

import atlantafx.base.theme.Styles;
import ch.qos.logback.core.util.StringUtil;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.control.TextInputControl;
import javafx.scene.control.TextInputDialog;
import javafx.scene.image.Image;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import lombok.extern.slf4j.Slf4j;
import net.rgielen.fxweaver.core.FxmlView;

/**
 * 编辑-添加表单
 * 
 * @author king
 * @date 2025年7月22日-15:00:53
 */
@Slf4j
@FxmlView
@Component
public class NovalEditForm {

	@FXML
	private VBox box;

	@FXML
	private TextField name;

	@FXML
	private TextField writer;

	@FXML
	private TextArea description;

	@FXML
	private TabPane volumePane;

	@FXML
	private Button saveBtn;

	@Autowired
	private ApplicationEventPublisher publisher;

	@Autowired
	private Async async;

	@Autowired
	private NovelService novelService;

	private String novelId;

	private BooleanProperty hasChange;

	private List<TextInputControl> forms;

	/**
	 * 保存，成功后回调
	 */
	private Consumer<Novel> callback;

	@FXML
	private void initialize() {
		init();
	}

	/**
	 * 表单重置
	 * 
	 * @author king
	 * @date 2025年7月22日-15:46:10
	 */
	public void resetForm() {
		name.clear();
		writer.clear();
		description.clear();
	}

	private void init() {
		hasChange = new SimpleBooleanProperty(false);
		forms = new ArrayList<>(List.of(name, writer, description));
		saveBtn.disableProperty().bind(hasChange.not());
		addListenter();
	}

	/**
	 * 给已经固定好的表单组件添加事件
	 */
	private void addListenter() {
		forms.forEach(i -> {
			addListener(i.textProperty());
		});
	}

	/**
	 * 给表单添加监听
	 */
	private void addListener(StringProperty s) {
		s.addListener((_, od, nw) -> {
			if (nw != null && !nw.equals(od)) {
				validate();
			}
		});
	}

	/**
	 * 校验
	 * 
	 * @author king
	 * @date 2025年7月23日-09:39:34
	 */
	private void validate() {
		boolean hc = true;
		for (TextInputControl t : forms) {
			if (StringUtil.isNullOrEmpty(t.getText())) {
				hc = false;
				break;
			}
		}
		hasChange.set(hc);
	}

	/**
	 * 添加卷
	 * 
	 * @author king
	 * @date 2025年7月22日-16:39:05
	 */
	@FXML
	private void onAddVolume() {
		addVolume(new NovelVolume(String.format("卷 %s", volumePane.getTabs().size() + 1)));
	}

	@FXML
	private void onCancel() {
		publisher.publishEvent(FormDialogEvent.close());
	}

	@FXML
	private void onSave() {
		Novel novel = new Novel();
		novel.setId(this.novelId);
		novel.setName(this.name.getText());
		novel.setDescription(this.description.getText());
		novel.setWriter(this.writer.getText());

		if (volumePane.getTabs().size() > 0) {
			List<NovelVolume> nvs = new ArrayList<>();
			NovelVolume nv;
			for (Tab t : volumePane.getTabs()) {
				nv = new NovelVolume();
				nv.setId(t.getId());
				nv.setNovelId(novelId);
				nv.setTitle(((Label) t.getGraphic()).getText());
				nv.setDescription(((TextArea) t.getContent()).getText());
				nvs.add(nv);
			}
			novel.setVolume(nvs);
		}

		async.done(() -> {
			return novelService.saveNovel(novel);
		}, (d) -> {
			if (d && callback != null) {
				callback.accept(novel);
				onCancel();
			}
		});

		log.info("novel:{}", novel);
	}

	/**
	 * 添加卷
	 * 
	 * @param volume
	 * @author king
	 * @date 2025年7月23日-09:38:00
	 */
	private void addVolume(NovelVolume volume) {
		Tab tab = new Tab();
		Label l = new Label();
		l.setText(volume.getTitle());

		if (!StringUtil.isNullOrEmpty(volume.getId())) {
			tab.setId(volume.getId());
		}
		TextArea area = new TextArea();

		forms.add(area);
		addListener(area.textProperty());
		area.getStyleClass().add("input-bg");
		area.setText(volume.getDescription());
		area.setPromptText("当前卷要写些什么...");
		validate();

		tab.setGraphic(l);
		tab.setContent(area);

		l.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> {
			if (e.getClickCount() >= 2) {
				TextInputDialog d = new TextInputDialog();
				d.setWidth(400);
				Button okButton = (Button) d.getDialogPane().lookupButton(ButtonType.OK);
				Button cancelButton = (Button) d.getDialogPane().lookupButton(ButtonType.CANCEL);
				if (okButton != null) {
					okButton.getStyleClass().addAll(Styles.FLAT, Styles.ACCENT);
					okButton.setGraphic(FontIcon.of(Feather.SAVE));
				}
				if (cancelButton != null) {
					cancelButton.getStyleClass().addAll(Styles.FLAT, Styles.DANGER);
					cancelButton.setGraphic(FontIcon.of(Feather.X_SQUARE));
				}
				((Stage) d.getDialogPane().getScene().getWindow()).getIcons()
						.add(new Image(getClass().getResourceAsStream(App.ICON)));
				d.setTitle("修改");
				d.getEditor().setText(l.getText());
				d.setContentText("名称");
				d.setHeaderText("请输入新的卷名称，如果要删除当前卷，须手动清空当前卷的所有内容后点击确定");
				d.showAndWait().ifPresent((val) -> {
					if (!StringUtil.isNullOrEmpty(val)) {
						l.setText(val);
					} else {
						if (StringUtil.isNullOrEmpty(area.getText())) {
							this.volumePane.getTabs().remove(tab);
							this.forms.remove(area);
						}
					}
					validate();
				});
			}
		});
		volumePane.getTabs().add(tab);
		// 将新添加的Tab设置为当前选中
		volumePane.getSelectionModel().select(tab);
	}

	/**
	 * 加载书本信息
	 * 
	 * @param novelId
	 * @author king
	 * @date 2025年7月22日-17:25:30
	 */
	public void loadData(String novelId, Consumer<Novel> callback) {
		this.callback = callback;
		if (novelId == null) {
			return;
		}
		async.done(()->{
			return novelService.loadBookBaseInfo(novelId);
		}, (d)->{
			this.novelId = d.getId();
			this.name.setText(d.getName());
			this.writer.setText(d.getWriter());
			this.description.setText(d.getDescription());
			this.volumePane.getTabs().clear();
			if (d.getVolume() != null && d.getVolume().size() > 0) {
				for (NovelVolume l : d.getVolume()) {
					addVolume(l);
				}
			}
		});
	}
}
